#include "inherite/Cat.hpp"
#include "inherite/Dog.hpp"
#include <iostream>
#include <vector>
#include <functional>
#include <memory>
#include <functional>

#include "exception/CustomException.hpp"

#include "simple_factory/OperationFactory.hpp"
#include "strategy/Context.hpp"

#include "decorate/Person.hpp"
#include "decorate/Clothes.hpp"
#include "decorate/Pants.hpp"

#include "proxy/MasterStore.hpp"
#include "proxy/SlaveStore.hpp"
#include "proxy/ISell.hpp"

#include "factory_method/AddOperationFactory.hpp"
#include "factory_method/SubOperationFactory.hpp"

#include "template_method/AscSort.hpp"
#include "template_method/DescSort.hpp"

#include "muti_thread.hpp"
#include "timer.hpp"

#include "facade/Facade.hpp"

#include "builder/Director.hpp"
#include "builder/ConcreteBuilderA.hpp"
#include "builder/ConcreteBuilderB.hpp"

#include "observer/BossSubject.hpp"
#include "observer/FoundObserver.hpp"
#include "observer/WatchNBAObserver.hpp"

#include "os/os.hpp"
#include "os/path/path.hpp"

#include "glob/glob.hpp"
#include "builder/ConcreteBuilderA.hpp"
#include "builder/ConcreteBuilderB.hpp"

#include "argsparse/ArgumentParser.hpp"

void ThrowException() {
    ThrowCustomExceptionInstance("自定义异常");
}

int CatchException() {
    try {
        ThrowException();
    } catch (const CustomException &e) {
        std::cout << "捕获到异常: " << e.what() << std::endl;
    }

    Cm_Release_Exception_Start;

    CatchException();

    Cm_Release_Exception_End({
        return -1;
    });
}

void InheritExample() {
    {
        std::vector<Animal_ptr> animals;

        animals.push_back(std::make_shared<Dog>()); 

        Animal_ptr animal = std::make_shared<Cat>("kitty");
        animals.push_back(animal);

        for (auto &animal : animals) {
            animal->Shout();
        }
    }

    printf ("================\n");

    Cat *cat = new Cat("hallokitty");
    Animal *animal = cat;
    cat->Run();
    delete animal;
}

void SimpleFactoryExample(int num1, int num2) { 
    IOperation_ptr add = OperationFactory::CreateOperation(OperationType::Add);
    add->num1 = num1;
    add->num2 = num2;

    IOperation_ptr sub = OperationFactory::CreateOperation(OperationType::Sub);
    sub->num1 = num1;
    sub->num2 = num2;

    std::cout << "sum: " << add->GetResult() << std::endl;
    std::cout << "sub: " << sub->GetResult() << std::endl;


    std::cout << "sum: " << (*add)(10, 5) << std::endl;
    std::cout << "sub: " << (*sub)(10, 5) << std::endl;
}

template <typename FUNC>
void func_runner(const FUNC &func) {
    func();
}

template <typename FUNC, typename... ARGS>
void func_runner(FUNC func, ARGS... args) {
    func(args...);
}

void FuncInvokeExample() {
    func_runner(InheritExample);
    func_runner(SimpleFactoryExample, 10, 5);
    func_runner([]{
        std::cout << "hello world" << std::endl;
    });

    Cat cat;

    func_runner([](Cat &cat) { cat.Shout(); }, cat);
}

void StrategyExample() {
    Context addContext(strategy::StrategyType::Add);
    auto res1 = addContext(10, 5);
    Context subContext(strategy::StrategyType::Sub);
    auto res2 = subContext(10, 5);

    std::cout << "add: " << res1 << std::endl;
    std::cout << "sub: " << res2 << std::endl;
}

void DecorateExample() {
    IDress_ptr xiaoming = std::make_shared<Person>("xiaoming");
    xiaoming = std::make_shared<Pants>(xiaoming);
    xiaoming = std::make_shared<Clothes>(xiaoming);

    xiaoming->Show();
}

void ProxyExample() {
    ISell_ptr masterStore = std::make_shared<MasterStore>();
    masterStore->Sell();

    ISell_ptr slaveStore = std::make_shared<SlaveStore>(masterStore);
    slaveStore->Sell();
}

void FactoryMethodExample() {
    IOperationFactory_ptr operationFactory = std::make_shared<AddOperationFactory>();
    IOperation_ptr operation = operationFactory->CreateOperationFactory();
    int result = (*operation)(5, 10);
    std::cout << "AddResult: " << result << std::endl;

    operationFactory = std::make_shared<SubOperationFactory>();
    operation = operationFactory->CreateOperationFactory();
    result = (*operation)(10, 5);
    std::cout << "SubResult: " << result << std::endl;
}

void TemplateMethodExample() { 
    AbstractSort_ptr<int> sortor = std::make_shared<DescSort<int>>();
    int arr[] = {2, 5, 3, 1, 4};
    sortor->Sorted(arr, 0, 4);

    std::cout << "DescSort: " << std::endl;
    for (int i = 0; i < 5; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;

    sortor = std::make_shared<AscSort<int>>();
    sortor->Sorted(arr, 0, 4);

    std::cout << "AscSort: " << std::endl;
    for (int i = 0; i < 5; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

void MutiThreadExample() {
    START_TIMER;
    std::thread t1(timer::sleep, 2);
    std::thread t2(timer::sleep, 2);
    t1.join();
    t2.join();
    // void __cdecl MutiThreadExample(void) 耗时: 2022 毫秒
}

void FacadeExample() {

    START_TIMER;

    std::cout << "Origin" << std::endl;
    // origin
    SubSystemA subSystemA;
    SubSystemB subSystemB;
    SubSystemC subSystemC;

    subSystemA.MethodA();
    subSystemC.MethodC();

    subSystemB.MethodB();
    subSystemC.MethodC();

    std::cout << "Facade" << std::endl;

    // facade
    Facade facade;
    facade.MethodOne();
    facade.MethodTwo();
}

void BuilderExample() {
    ConcreteBuilderA builder_a = ConcreteBuilderA();
    ConcreteBuilderB builder_b = ConcreteBuilderB();

    Director director = Director();

    Product product_a = director.Constract(builder_a);
    Product product_b = director.Constract(builder_b);

    std::cout << "product_a: " << product_a << std::endl;
    std::cout << "product_b: " << product_b << std::endl;
}

void ObserverExample() {
    BossSubject bossSubject = BossSubject();

    Observer_ptr foundObserver = std::make_shared<FoundObserver>();
    Observer_ptr watchNBAObserver = std::make_shared<WatchNBAObserver>();

    bossSubject.AddObserver(foundObserver);
    bossSubject.AddObserver(watchNBAObserver);

    bossSubject.Notify("found");
}

void Exmaple() {
    std::string dirname = "output";
    if (!os::path::exists(dirname)) {
        os::makedirs(dirname);
        std::cout << "创建目录成功" << std::endl;
    }

    std::string data_path = "include";

    std::string test = os::path::join(data_path, "test");
    os::makedirs(test);


    std::cout << "size: " << os::listdir(data_path).size() << std::endl;

    std::cout << os::path::exists(data_path) << std::endl;

    data_path = os::path::abspath(data_path);

    std::string source_path = os::path::join(data_path, "*.hpp");

    std::cout << "source_path: " << source_path << std::endl;

    auto files = glob::glob(source_path);

    std::cout << "files: " << files.size() << std::endl;
    for (auto &file : files) {
        std::cout << file << std::endl;
    }
}

int parse_args(int argc, char* argv[]) {
    try {
        // 创建参数解析器
        argparse::ArgumentParser parser(
            "file_processor",  // 程序名称
            "A simple file processing tool",  // 描述
            "For more information, visit: https://example.com"  // 结尾信息
        );
        
        // 添加位置参数（输入文件）
        parser.add_argument("input_file")
              .help("Input file to process");
        
        // 添加可选参数（输出文件）
        parser.add_argument("--output", "-o")
              .help("Output file (default: output.txt)")
              .default_value("output.txt");
        
        // 添加布尔标志参数（详细模式）
        parser.add_argument("--verbose", "-v")
              .help("Enable verbose output")
              .action("store_true");
        
        // 添加必需参数（处理模式）
        parser.add_argument("--mode", "-m")
              .help("Processing mode")
              .required(true)
              .choices({"copy", "reverse", "uppercase"});
        
        // 添加整数参数（重复次数）
        parser.add_argument("--repeat", "-r")
              .help("Number of times to repeat processing")
              .default_value("1")
              .type("int");
        
        // 添加浮点数参数（缩放因子）
        parser.add_argument("--scale", "-s")
              .help("Scaling factor for processing")
              .default_value("1.0")
              .type("float");
        
        // 解析参数
        auto args = parser.parse_args(argc, argv);
        
        // 获取参数值
        std::string input_file = args["input_file"];
        std::string output_file = args["output"];
        bool verbose = parser.get_bool("verbose");
        std::string mode = args["mode"];
        int repeat = parser.get_int("repeat");
        double scale = parser.get_float("scale");
        
        // 打印参数信息（如果启用详细模式）
        if (verbose) {
            std::cout << "=== Configuration ===" << std::endl;
            std::cout << "Input file: " << input_file << std::endl;
            std::cout << "Output file: " << output_file << std::endl;
            std::cout << "Mode: " << mode << std::endl;
            std::cout << "Repeat: " << repeat << std::endl;
            std::cout << "Scale: " << scale << std::endl;
            std::cout << "=====================" << std::endl;
        }        
    } catch (const argparse::ArgumentError& e) {
        std::cerr << "Argument error: " << e.what() << std::endl;
        std::cerr << "Use --help for usage information." << std::endl;
        return 1;
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}

int main(int argc, char* argv[]) {

    try {
        // InheritExample();
        // SimpleFactoryExample(10, 5);
        // StrategyExample();
        // DecorateExample();
        // ProxyExample();
        // FactoryMethodExample();
        //TemplateMethodExample();
        // MutiThreadExample();
        // FacadeExample();
        // BuilderExample();
        // ObserverExample();
        // Exmaple();
        parse_args(argc, argv);
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }

    return 0;
}